package cn.deepmax.spring.cloud.common.web;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import java.util.List;
import java.util.Optional;

/**
 * 参数校验
 * @author zhaohw
 * @date 2019-01-10 17:46
 */
@Slf4j
public abstract class BindingParamsBaseAspect implements ApplicationContextAware {


    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     *
     */
    public abstract Object around(ProceedingJoinPoint joinPoint) throws Throwable;

    /**
     * 如果SelfValidated 后面没有跟BindingResult 则直接调用
     * 否则，先过BindingResult 然后再自检
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    protected Object around0(ProceedingJoinPoint joinPoint) throws Throwable{


        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            Object arg = args[i];
            if(arg instanceof ArrayQuery){
                ArrayQuery query = (ArrayQuery) arg;
                ArrayQuerySupport.transform(query);
            }
            if(arg instanceof BindingResult){
                BindingResult bindingResult = (BindingResult) arg;
                if (bindingResult.hasErrors()) {
                    List<FieldError> errorList = bindingResult.getFieldErrors();
                    //取首个校验失败参数的错误信息
                    return AjaxResponse.validateFail(errorList.get(0).getDefaultMessage());
                }
                if(i!=0){
                    Object preArg = args[i-1];
                    if(preArg instanceof SelfValidated){
                        Optional<AjaxResponse> ajaxResponse = validateSelf(preArg);
                        if(ajaxResponse.isPresent())
                            return ajaxResponse.get();
                    }
                }
            }
            if(arg instanceof SelfValidated){
                if(i!=args.length-1){
                    Object nextArg = args[i+1];
                    if(!(nextArg instanceof BindingResult)){
                        Optional<AjaxResponse> ajaxResponse = validateSelf(arg);
                        if(ajaxResponse.isPresent())
                            return ajaxResponse.get();
                    }
                }else{
                    Optional<AjaxResponse> ajaxResponse = validateSelf(arg);
                    if(ajaxResponse.isPresent())
                        return ajaxResponse.get();
                }
            }
        }
        Object result = joinPoint.proceed();
        return result;
    }


    private Optional<AjaxResponse> validateSelf(Object obj){
        SelfValidated en = (SelfValidated) obj;
        Optional<AjaxResponse> result = en.validate(applicationContext);
        return result;
    }

}
